# coding: utf-8
# Author: zhenda

import random
from flask_restful import Resource
from flask_restful.reqparse import RequestParser  # 请求参数验证
from flask import current_app, request, g
from comment.models.user import User
from comment.utils.huyi_sms_send import sms_send
import json
from comment.utils.limiter import limiter
from . import constants
from flask_limiter.util import get_remote_address
from comment.utils.shopping_redis import redis_client
from comment.utils import parser
from comment.models import db
from comment.utils.tokens_pyjwt import generate_tokens
from comment.utils.decorators import login_required


# 测试用的类
class Shopping_User(Resource):
    # 添加装饰器
    method_decorators = {
        'get': [login_required],
        'post': [login_required],

    }

    def get(self):  # 登录后才能访问
        current_app.logger.info('我的info日志')
        current_app.logger.error('错误')
        return {'hello': 'get测试'}

    def post(self):  # 登录后才能访问
        return {'hello': 'post测试'}

    def put(self):  # 登录后才能访问
        return {'hello': 'put测试'}


class User_SMS(Resource):
    """
    发送验证码的短信。
    """
    error_msg = 'too many requests'
    # 添加了限流器，防止无限请求验证码
    decorators = [
        limiter.limit(constants.LIMIT_SMS_CODE_BY_MOBILE,
                      key_func=lambda: request.args.get('phone'),
                      error_message=error_msg),
        limiter.limit(constants.LIMIT_SMS_CODE_BY_IP,
                      key_func=get_remote_address,
                      error_message=error_msg)

    ]

    def get(self):
        phone = request.args.get('phone').strip()
        code_num = random.randint(100000, 999999)
        rst = sms_send(phone, code_num)  # 发送短信
        rst = json.loads(rst)  # 把str变成字典
        rst['phone'] = phone

        # 把验证码放到redis数据库中, 存5min
        redis_client.setex('shopping:code:{}'.format(phone), constants.SMS_CODE_EXPIRES, code_num)
        return rst  # flask会自动把字典变成json格式


class AuthorizationCodeResource(Resource):
    """
    验证 用户提交的验证码
    """

    def post(self):
        rp = RequestParser()
        rp.add_argument('phone', type=parser.is_mobile, required=True)
        rp.add_argument('code', type=parser.regex(r'^\d{6}$'), required=True)
        args = rp.parse_args()
        phone = args.phone
        code_num = args.code
        # print(phone,code_num)
        # 从redis得到保存的验证码
        key = f'shopping:code:{phone}'
        try:
            real_code = redis_client.get(key).decode('utf8')  # 从redis 返回字节数据
        except ConnectionError as e:
            current_app.logger.error(e)  # 调用自身的errorlog
            return {'message': 'redis db connect error'}, 400
        if not real_code or real_code != code_num:
            return {'message': 'Invalid code'}, 400

        return {'phone': phone, 'msg': 'code success.'}


class RegisterUserResource(Resource):
    """
    用户注册
    """

    def post(self):
        rp = RequestParser()
        rp.add_argument('phone', type=parser.is_mobile, required=True)
        rp.add_argument('username', required=True)
        rp.add_argument('password', required=True)
        rp.add_argument('email', type=parser.is_email, required=True)
        args = rp.parse_args()
        phone = args.phone
        username = args.username
        password = args.password
        email = args.email

        # 用户名是否唯一 1.
        u = User.query.filter(User.username == username).first()
        if u:  # 用户名已经存在
            current_app.logger.info('{}:用户名已经存在，请换一个'.format(username))
            return {'message': '用户名已存在.'}, 400

        # 验证邮箱是否唯一 :先从mysql数据库中根据当前邮箱查询
        u = User.query.filter(User.email == email).first()
        if u:  # 用户名已经存在
            current_app.logger.info('{}:邮箱地址已经存在，请换一个'.format(username))
            return {'message': '邮箱地址已存在.'}, 410

        # 把用户信息保存到数据库中
        u = User(username=username, pwd=password, email=email, status=0, phone=phone)  # 密码进行加密，保存密文
        db.session.add(u)
        db.session.commit()
        return {'msg': 'ok', 'code': 200}


class UserLoginResource(Resource):
    """
    登录
    """

    # 表单提交
    def post(self):
        username = request.form.get('username')
        password = request.form.get('password')

        if not all([username, password]):  # all() 判断多个变量是否为空
            return {'message': '数据不完整'}, 402
        user = User.query.filter(User.username == username).first()
        if user:
            if user.check_password(password):
                # token 的步骤
                # 1.需要把登录成功的用户id得到token， token返回给前端
                token = generate_tokens(user.id)
                return {'msg': 'Login Success.', 'token': token, 'username': username}
        return {'message': '用户名或密码错误'}, 400  # 400：状态码， 最好给前端


class UserLoginOutResource(Resource):
    """
    退出
    """

    def post(self):
        if g.user_id:
            g.user_id = None
        return {'msg': 'logout Done'}


class IsExistPhone(Resource):
    """
    手机号是否存在
    """

    # 表单提交
    def post(self):
        phone = request.form.get('phone')
        user = User.query.filter(User.phone == phone).first()
        if user:
            return {'isExist': True, 'message': '此手机号码已经注册', 'code': 203}
        return {'msg': '可以注册此手机号码'}
